package com.xianyu.open.restclient.handler;

import com.xianyu.open.restclient.config.MethodInfo;
import com.xianyu.open.restclient.config.ServerInfo;
import com.xianyu.open.restclient.constants.RestClientGlobalConstants;
import com.xianyu.open.restclient.factory.SingletonFactoryBean;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

/**
 * @author bailinan
 */
public abstract class RestClientHandler {

    /**
     * 执行处理器
     * @param serverInfo
     * @param methodInfo
     * @param resultType
     * @param <T>
     * @return
     */
    public abstract <T> T invokeHandler(ServerInfo serverInfo, MethodInfo methodInfo, Class<T> resultType);


    public static RestClientHandler getWebMvcInstance(){
        return SingletonFactoryBean.getObject("webMvc", WebMvcRestClientHandler::new);
    }

    public static RestClientHandler getWebFluxInstance(){
        // TODO 待实现
        return null;
    }

    /**
     * 获取url
     * @param serverInfo
     * @param methodInfo
     * @return
     */
    protected String getUrl(ServerInfo serverInfo, MethodInfo methodInfo){
        return serverInfo.getServerAddress() + methodInfo.getRelUrl();
    }

    /**
     * 获取url参数
     * @param url
     * @param uriVariables
     * @return
     */
    protected Object[] getUriVariables(String url, Map<String, Object> uriVariables) {
        List<String> urlParamNames= new ArrayList<>();
        List<Object> urlParamValues = new ArrayList<>();
        Matcher matcher = RestClientGlobalConstants.URI_PARAM_RULE.matcher(url);
        while (matcher.find()){
            urlParamNames.add(matcher.group(1));
        }
        urlParamNames.forEach(s -> {
            if (uriVariables.get(s) == null){
                throw new RuntimeException();
            }else {
                urlParamValues.add(uriVariables.get(s));
            }
        });
        return urlParamValues.toArray();
    }

    /**
     * 获取真实请求体
     * @param methodInfo
     * @return
     */
    protected Object getRequestParam(MethodInfo methodInfo){
        return methodInfo.getRequestBody() == null? methodInfo.getRequestParam():methodInfo.getRequestBody();
    }
}
